import throttle from "./throttle";

/**
 * 重置模态框水平居中
 * @param modalEl 模态框元素对象DOM
 * @param width 模态框初始宽度
 * @param centerY 模态框横向居中，顶部偏离100px
 */
export function resetModalCenterY(modalEl: HTMLDivElement, centerY: boolean) {
  if (!modalEl) return;
  const clientWidth = document.documentElement.clientWidth;
  const offsetWidth = modalEl.offsetWidth;
  if (centerY) {
    modalEl.style.top = "100px";
    modalEl.style.left = `${(clientWidth - offsetWidth) / 2}px`;
  }
  if (modalEl.style.left !== "") return;
  if (clientWidth >= offsetWidth) {
    modalEl.style.left = `${(clientWidth - offsetWidth) / 2}px`;
  }
}

/**
 * 重置模态框最小宽度/高度
 * @param modalEl 模态框元素对象DOM
 * @param minWidth 最小宽度
 * @param minHeight 最小高度
 */
export function resetModalMinWH(
  modalEl: HTMLDivElement,
  minWidth: number,
  minHeight: number
) {
  if (!modalEl) return;
  const offsetWidth = modalEl.offsetWidth;
  const offsetHeight = modalEl.offsetHeight;
  if (offsetWidth < minWidth) {
    modalEl.style.width = `${minWidth}px`;
  }
  if (offsetHeight < minHeight) {
    modalEl.style.height = `${minHeight}px`;
  }
}

/**
 * 当超过屏幕显示范围将收敛模态框大小
 * @param modalWrapEl 模态底层容器元素对象DOM
 * @param modalEl 模态框元素对象DOM
 */
export function resetModalWH(
  modalWrapEl: HTMLDivElement,
  modalEl: HTMLDivElement
) {
  if (!modalEl) return;
  const clientWidth = modalWrapEl.clientWidth;
  const clientHeight = modalWrapEl.clientHeight;

  const offsetWidth = modalEl.offsetWidth;
  const offsetHeight = modalEl.offsetHeight;

  if (offsetWidth >= clientWidth) {
    modalEl.style.width = `${clientWidth}px`;
  }
  if (offsetHeight >= clientHeight) {
    modalEl.style.top = "0px";
    modalEl.style.height = `${clientHeight}px`;
  }
}

/**
 * 注册模态框可拖动元素
 * @param modalEl 模态框元素对象DOM
 * @param dragEl 要按住的拖动元素对象DOM
 * @param disabled 禁用拖动，传入布尔函数
 * @param callback 按下回调监听函数
 */
export function registerModalDrag(
  modalEl: HTMLDivElement,
  dragEl: HTMLDivElement,
  disabled: () => boolean,
  callback: () => void
) {
  dragEl.style.cursor = "move";
  dragEl.addEventListener("mousedown", startDrag);
  dragEl.addEventListener("mousemove", () => {
    if (disabled()) {
      if (dragEl.style.cursor !== "auto") {
        dragEl.style.cursor = "auto";
      }
      return;
    }
    if (dragEl.style.cursor !== "move") {
      dragEl.style.cursor = "move";
    }
  });

  let rect: DOMRect;
  let offsetX: number, offsetY: number;
  let maxLeft: number, maxTop: number;

  /**按住拖动元素移动白改变模态框位置 */
  function startDrag(event: MouseEvent) {
    if (disabled()) return;
    event.preventDefault(); // 阻止默认行为，避免文本选中等问题
    document.body.style.userSelect = "none";

    rect = modalEl.getBoundingClientRect();
    offsetX = event.clientX - rect.left;
    offsetY = event.clientY - rect.top;
    maxLeft = document.documentElement.clientWidth - rect.width;
    maxTop = document.documentElement.clientHeight - rect.height;

    document.addEventListener("mousemove", drag);
    document.addEventListener("mouseup", stopDrag);
  }

  /**按住拖动模态框的位置变更 */
  function drag(event: MouseEvent) {
    if (disabled()) return;

    const left = Math.min(Math.max(event.clientX - offsetX, 0), maxLeft);
    const top = Math.min(Math.max(event.clientY - offsetY, 0), maxTop);

    // 使用 requestAnimationFrame 合并DOM更新
    window.requestAnimationFrame(() => {
      modalEl.style.left = `${left}px`;
      modalEl.style.top = `${top}px`;
      // 执行回调函数
      callback();
    });
  }

  /**移除鼠标移动和按住的监听 */
  function stopDrag() {
    document.removeEventListener("mousemove", drag);
    document.removeEventListener("mouseup", stopDrag);
    document.body.style.userSelect = "auto";
  }
}

/**
 * 鼠标边显示样式
 * https://developer.mozilla.org/zh-CN/docs/Web/CSS/cursor
 */
const cursorStyle = {
  /**向上 */
  top: "n-resize",
  /**向左 */
  left: "w-resize",
  /**向右 */
  right: "e-resize",
  /**向下 */
  bottom: "s-resize",
  /**左上角 */
  topLeft: "nw-resize",
  /**右上角 */
  topright: "ne-resize",
  /**右上角 */
  bottomLeft: "sw-resize",
  /**右下角 */
  bottomRight: "se-resize",
  /**默认样式 */
  auto: "auto",
};

/**
 * 注册模态框边界拉伸元素
 * @param modalWrapEl 模态框元素决定拉伸范围的外层对象DOM
 * @param modalEl 模态框元素对象DOM
 * @param minWidth 最小宽度
 * @param minHeight 最小高度
 * @param disabled 禁用拉伸，传入布尔函数
 * @param callback 按下回调监听函数
 */
export function registerModalBorderDraw(
  modalWrapEl: HTMLDivElement,
  modalEl: HTMLDivElement,
  minWidth: number,
  minHeight: number,
  disabled: () => boolean,
  callback: () => void
) {
  /**鼠标移动到模态框边界改变鼠标样式 */
  modalWrapEl.onmousemove = throttle((event: MouseEvent) => {
    if (disabled()) return;
    const top = event.clientY - modalEl.offsetTop;
    const left = event.clientX - modalEl.offsetLeft;
    const right = event.clientX - modalEl.offsetWidth - modalEl.offsetLeft;
    const bottom = event.clientY - modalEl.offsetHeight - modalEl.offsetTop;

    // 定义阈值常量
    const BORDER_THRESHOLD = 5;
    const CORNER_THRESHOLD = 8;

    // 判断鼠标位置并设置相应的样式
    if (
      left <= BORDER_THRESHOLD &&
      left > -CORNER_THRESHOLD &&
      top > BORDER_THRESHOLD &&
      bottom < -BORDER_THRESHOLD
    ) {
      modalWrapEl.style.cursor = cursorStyle.left; // 向左
    } else if (
      top < BORDER_THRESHOLD &&
      top > -CORNER_THRESHOLD &&
      left > BORDER_THRESHOLD &&
      right < -BORDER_THRESHOLD
    ) {
      modalWrapEl.style.cursor = cursorStyle.top; // 向上
    } else if (
      right >= -CORNER_THRESHOLD &&
      right < BORDER_THRESHOLD &&
      top > BORDER_THRESHOLD &&
      bottom < -BORDER_THRESHOLD
    ) {
      modalWrapEl.style.cursor = cursorStyle.right; // 向右
    } else if (
      bottom > -CORNER_THRESHOLD &&
      bottom < BORDER_THRESHOLD &&
      left > BORDER_THRESHOLD &&
      right < -BORDER_THRESHOLD
    ) {
      modalWrapEl.style.cursor = cursorStyle.bottom; // 向下
    } else if (
      left > -CORNER_THRESHOLD &&
      left <= BORDER_THRESHOLD &&
      top <= BORDER_THRESHOLD &&
      top > -CORNER_THRESHOLD
    ) {
      modalWrapEl.style.cursor = cursorStyle.topLeft; // 左上角
    } else if (
      left > -CORNER_THRESHOLD &&
      left <= BORDER_THRESHOLD &&
      bottom <= BORDER_THRESHOLD &&
      bottom > -CORNER_THRESHOLD
    ) {
      modalWrapEl.style.cursor = cursorStyle.bottomLeft; // 左下角
    } else if (
      right < CORNER_THRESHOLD &&
      right >= -BORDER_THRESHOLD &&
      top <= BORDER_THRESHOLD &&
      top > -CORNER_THRESHOLD
    ) {
      modalWrapEl.style.cursor = cursorStyle.topright; // 右上角
    } else if (
      right < CORNER_THRESHOLD &&
      right >= -BORDER_THRESHOLD &&
      bottom <= BORDER_THRESHOLD &&
      bottom > -CORNER_THRESHOLD
    ) {
      modalWrapEl.style.cursor = cursorStyle.bottomRight; // 右下角
    } else {
      modalWrapEl.style.cursor = cursorStyle.auto; // 默认样式
    }
  }, 100);
  /**鼠标到模态框边界按下 */
  modalWrapEl.onmousedown = throttle((event: MouseEvent) => {
    if (disabled()) return;
    const rect = modalEl.getBoundingClientRect();
    const disX = event.clientX - rect.left;
    const disY = event.clientY - rect.top;
    const parentWidth = modalEl.offsetWidth;
    const parentHeight = modalEl.offsetHeight;
    const cursor = modalWrapEl.style.cursor;

    const handleMouseMove = (e: MouseEvent) => {
      if (disabled()) return;
      if (cursor !== cursorStyle.auto) {
        document.body.style.userSelect = "none";
      }

      // 定位左
      const leftMax = Math.max(0, e.clientX - disX);
      const mLeft = `${Math.min(leftMax, rect.left)}px`;
      // 定位左上
      const topMax = Math.max(0, e.clientY - disY);
      const mTop = `${Math.min(topMax, rect.top)}px`;
      // 向左拉宽度
      const leftWidthMax = Math.min(
        rect.right,
        parentWidth + rect.left - e.clientX
      );
      const mLeftWidth = `${Math.max(leftWidthMax, parentWidth)}px`;
      // 向右拉宽度
      const rightWidthMax = Math.min(
        window.innerWidth - rect.left,
        e.clientX - rect.left
      );
      const mRightWidth = `${Math.max(rightWidthMax, minWidth)}px`;
      // 向上拉高度
      const topHeightMax = Math.min(
        rect.bottom,
        parentHeight + rect.top - e.clientY
      );
      const mTopHeight = `${Math.max(topHeightMax, parentHeight)}px`;
      // 向下拉高度
      const bottomHeightMax = Math.min(
        window.innerHeight - rect.top,
        e.clientY - rect.top
      );
      const mBottomHeight = `${Math.max(bottomHeightMax, minHeight)}px`;

      // 使用 requestAnimationFrame 合并DOM更新
      window.requestAnimationFrame(() => {
        // 向左边拖拽
        if (cursor === cursorStyle.left) {
          modalEl.style.left = mLeft;
          modalEl.style.width = mLeftWidth;
          // 向上边拖拽
        } else if (cursor === cursorStyle.top) {
          modalEl.style.top = mTop;
          modalEl.style.height = mTopHeight;
          // 向右边拖拽
        } else if (cursor === cursorStyle.right) {
          modalEl.style.width = mRightWidth;
          // 向下拖拽
        } else if (cursor === cursorStyle.bottom) {
          modalEl.style.height = mBottomHeight;
          // 左上角拖拽
        } else if (cursor === cursorStyle.topLeft) {
          modalEl.style.left = mLeft;
          modalEl.style.top = mTop;
          modalEl.style.height = mTopHeight;
          modalEl.style.width = mLeftWidth;
          // 右上角拖拽
        } else if (cursor === cursorStyle.topright) {
          modalEl.style.top = mTop;
          modalEl.style.width = mRightWidth;
          modalEl.style.height = mTopHeight;
          // 左下角拖拽
        } else if (cursor === cursorStyle.bottomLeft) {
          modalEl.style.left = mLeft;
          modalEl.style.width = mLeftWidth;
          modalEl.style.height = mBottomHeight;
          // 右下角拖拽
        } else if (cursor === cursorStyle.bottomRight) {
          modalEl.style.width = mRightWidth;
          modalEl.style.height = mBottomHeight;
        }
        // 执行回调函数
        callback();
      });
    };

    const handleMouseUp = () => {
      document.removeEventListener("mousemove", handleMouseMove);
      document.removeEventListener("mouseup", handleMouseUp);
      document.body.style.userSelect = "auto";
      modalWrapEl.style.cursor = cursorStyle.auto;
    };

    document.addEventListener("mousemove", handleMouseMove);
    document.addEventListener("mouseup", handleMouseUp);
  }, 100);
}
